package com.summer.filesync.service;

import com.summer.filesync.database.dao.FileMetadataDAO;
import com.summer.filesync.database.dao.impl.FileMetadataDAOImpl;
import com.summer.filesync.model.FileMetadata;
import com.summer.filesync.sync.FileEvent;
import com.summer.filesync.util.FileUtils;
import com.summer.filesync.util.Logger;
import java.io.File;
import java.util.List;
import java.util.Optional;

/** 文件同步服务 处理文件变化事件，实现文件同步逻辑 */
public class FileSyncService {

  private static final Logger logger = Logger.getLogger(FileSyncService.class);
  private final FileMetadataDAO fileMetadataDAO;
  private final String nodeId;

  public FileSyncService(String nodeId) {
    this.nodeId = nodeId;
    this.fileMetadataDAO = new FileMetadataDAOImpl();
  }

  /**
   * 处理文件事件
   *
   * @param event 文件事件
   */
  public void handleFileEvent(FileEvent event) {
    logger.info("Processing file event: " + event.getType() + " for " + event.getFilePath());

    switch (event.getType()) {
      case CREATED:
        handleFileCreated(event);
        break;
      case MODIFIED:
        handleFileModified(event);
        break;
      case DELETED:
        handleFileDeleted(event);
        break;
      default:
        logger.warn("Unknown event type: " + event.getType());
    }
  }

  /** 处理文件创建事件 */
  private void handleFileCreated(FileEvent event) {
    try {
      File file = new File(event.getFilePath());
      if (!file.exists()) {
        logger.warn("File does not exist: " + event.getFilePath());
        return;
      }

      // 检查是否已存在记录
      Optional<FileMetadata> existing = fileMetadataDAO.findByFilePath(event.getFilePath());
      if (existing.isPresent()) {
        logger.info("File already exists in database, updating: " + event.getFilePath());
        handleFileModified(event);
        return;
      }

      // 创建新的文件元数据
      FileMetadata metadata = createFileMetadata(file);
      fileMetadataDAO.save(metadata);

      logger.info("File metadata saved: " + metadata.getFilePath());

    } catch (Exception e) {
      logger.error("Error handling file created event: " + event.getFilePath(), e);
    }
  }

  /** 处理文件修改事件 */
  private void handleFileModified(FileEvent event) {
    try {
      File file = new File(event.getFilePath());
      if (!file.exists()) {
        logger.warn("Modified file does not exist: " + event.getFilePath());
        handleFileDeleted(event);
        return;
      }

      Optional<FileMetadata> existing = fileMetadataDAO.findByFilePath(event.getFilePath());

      if (existing.isPresent()) {
        // 更新现有记录
        FileMetadata metadata = existing.get();
        updateFileMetadata(metadata, file);
        fileMetadataDAO.update(metadata);

        logger.info("File metadata updated: " + metadata.getFilePath());
      } else {
        // 创建新记录
        logger.info("File not found in database, creating new record: " + event.getFilePath());
        handleFileCreated(event);
      }

    } catch (Exception e) {
      logger.error("Error handling file modified event: " + event.getFilePath(), e);
    }
  }

  /** 处理文件删除事件 */
  private void handleFileDeleted(FileEvent event) {
    try {
      Optional<FileMetadata> existing = fileMetadataDAO.findByFilePath(event.getFilePath());

      if (existing.isPresent()) {
        // 标记为已删除或直接删除记录
        FileMetadata metadata = existing.get();
        metadata.setStatus(FileMetadata.FileStatus.DELETED);
        fileMetadataDAO.update(metadata);

        // 或者直接删除记录
        // fileMetadataDAO.delete(metadata);

        logger.info("File marked as deleted: " + metadata.getFilePath());
      } else {
        logger.warn("Deleted file not found in database: " + event.getFilePath());
      }

    } catch (Exception e) {
      logger.error("Error handling file deleted event: " + event.getFilePath(), e);
    }
  }

  /** 创建文件元数据 */
  private FileMetadata createFileMetadata(File file) {
    FileMetadata metadata = new FileMetadata();
    metadata.setFilePath(file.getAbsolutePath());
    metadata.setFileSize(file.length());
    metadata.setLastModified(file.lastModified());
    metadata.setDirectory(file.isDirectory());
    metadata.setNodeId(nodeId);

    // 计算文件哈希和校验和
    if (!file.isDirectory()) {
      try {
        String checksum = FileUtils.calculateChecksum(file.getAbsolutePath());
        metadata.setChecksum(checksum);

        String fileHash = FileUtils.calculateSHA256(file.getAbsolutePath());
        metadata.setFileHash(fileHash);
      } catch (Exception e) {
        logger.error("Error calculating file hash: " + file.getAbsolutePath(), e);
      }
    }

    return metadata;
  }

  /** 更新文件元数据 */
  private void updateFileMetadata(FileMetadata metadata, File file) {
    metadata.setFileSize(file.length());
    metadata.setLastModified(file.lastModified());
    metadata.setDirectory(file.isDirectory());

    // 重新计算文件哈希和校验和
    if (!file.isDirectory()) {
      try {
        String checksum = FileUtils.calculateChecksum(file.getAbsolutePath());
        metadata.setChecksum(checksum);

        String fileHash = FileUtils.calculateSHA256(file.getAbsolutePath());
        metadata.setFileHash(fileHash);
      } catch (Exception e) {
        logger.error("Error recalculating file hash: " + file.getAbsolutePath(), e);
      }
    }
  }

  /**
   * 同步指定目录
   *
   * @param directoryPath 目录路径
   */
  public void syncDirectory(String directoryPath) {
    logger.info("Starting directory sync: " + directoryPath);

    File directory = new File(directoryPath);
    if (!directory.exists() || !directory.isDirectory()) {
      logger.error("Directory does not exist or is not a directory: " + directoryPath);
      return;
    }

    syncDirectoryRecursive(directory);
    logger.info("Directory sync completed: " + directoryPath);
  }

  /** 递归同步目录 */
  private void syncDirectoryRecursive(File directory) {
    File[] files = directory.listFiles();
    if (files == null) {
      return;
    }

    for (File file : files) {
      try {
        Optional<FileMetadata> existing = fileMetadataDAO.findByFilePath(file.getAbsolutePath());

        if (existing.isPresent()) {
          // 检查是否需要更新
          FileMetadata metadata = existing.get();
          if (file.lastModified() > metadata.getLastModified()
              || file.length() != metadata.getFileSize()) {

            updateFileMetadata(metadata, file);
            fileMetadataDAO.update(metadata);
            logger.debug("Updated metadata for: " + file.getAbsolutePath());
          }
        } else {
          // 创建新记录
          FileMetadata metadata = createFileMetadata(file);
          fileMetadataDAO.save(metadata);
          logger.debug("Created metadata for: " + file.getAbsolutePath());
        }

        // 递归处理子目录
        if (file.isDirectory()) {
          syncDirectoryRecursive(file);
        }

      } catch (Exception e) {
        logger.error("Error syncing file: " + file.getAbsolutePath(), e);
      }
    }
  }

  /**
   * 获取需要同步的文件列表
   *
   * @return 需要同步的文件列表
   */
  public List<FileMetadata> getFilesNeedingSync() {
    return fileMetadataDAO.findFilesNeedingSync();
  }

  /**
   * 获取指定目录下的所有文件
   *
   * @param directoryPath 目录路径
   * @return 文件列表
   */
  public List<FileMetadata> getFilesByDirectory(String directoryPath) {
    return fileMetadataDAO.findByDirectory(directoryPath);
  }

  /**
   * 根据文件哈希查找重复文件
   *
   * @param fileHash 文件哈希
   * @return 重复文件列表
   */
  public List<FileMetadata> findDuplicateFiles(String fileHash) {
    return fileMetadataDAO.findByFileHash(fileHash);
  }

  /**
   * 获取数据库中的文件总数
   *
   * @return 文件总数
   */
  public long getTotalFileCount() {
    return fileMetadataDAO.count();
  }
}
